#include <iostream>
#include <typeinfo>
#include <string>
// #include <any>
#include <utility>

class Any
{
private:
    class holder
    {
    public:
        virtual ~holder()
        {}
        virtual const std::type_info& type() = 0;
        virtual holder* clone() = 0;
    };
    template<class T>
    class placeholder : public holder
    {
    public:
        placeholder(const T& val = T()):_val(val)
        {}
        virtual const std::type_info& type()//获取子类对象保存的数据 -- 返回类型是const type_info&
        {
            return typeid(T);
        }
        virtual holder* clone()//针对当前的对象自身，克隆出一个新的子类对象
        {
            return new placeholder(_val);
        }
    public:
        T _val;
    };

    holder* _content;

    public:
        Any()
        :_content(NULL)
        {}
        template<class T>
        Any(const T& val)
        :_content(new placeholder<T>(val))
        {}
        Any(const Any& other)
        :_content(other._content ? other._content->clone() : NULL)
        {}
        ~Any()
        {
            delete _content;
        }
        Any& swap(Any& other)
        {
            std::swap(_content, other._content);
            return *this;
        }

        template<class T>
        T* get()       //返回子类对象保存数据的指针
        {
            if (typeid(T) != _content->type()) //如果你要的类型和我保存的类型不匹配
                return NULL;
            return &(((placeholder<T>*)_content)->_val);
        }

        template<class T>
        Any& operator=(const T& val)//赋值运算符的重载函数
        {
            //为val构造一个临时的通用容器，然后与当前的容器自身进行指针交换，临时对象释放的时候，原先保存的数据也就被释放了
            Any(val).swap(*this);
            return *this;
        }
        Any& operator=(const Any& other)
        {
            Any(other).swap(*this);
            return *this;
        }
};


class Test
{
public:
    Test()
    {
        std::cout << "Test()" << std::endl;
    }
    Test(const Test& t)
    {
        std::cout << "Test()" << std::endl;
    }
    ~Test()
    {
        std::cout << "~Test()" << std::endl;
    }
};

int main()
{
    //官方any的使用方法，主要还是要查文档
    //std::any a;
    //a = 10;
    //int* pi = std::any_cast<int>(&a);
    //std::cout << *pi << std::endl;

    //a = std::string("hello");
    //std::string* ps = std::any_cast<std::string>(&a);
    //std::cout << *ps << std::endl;


    Test t;
    Any a(t);
    // Any a;
    a = std::string("string");
    std::string* pa = a.get<std::string>();
    std::cout << *pa << std::endl;
    Any b;
    b = 123;
    int* pb = b.get<int>();
    std::cout << *pb << std::endl;
    return 0;
}
